#include "verifierSYNCHRONIE.h"
#include <vector>

/******************************************************************************************************/
// La but de cette fonction est de faire la synchronie entre des populations locales
// avec les memes valeurs initiales des variables S0, E0, I0, R0
vector<string> faireSYNCH_identique(vector<double> valParSIM, char SAUVER[5]){
    //villes toutes identiques
    //valSEIR0.clear();
    vector<string> vecNomFichRes = simulerSEIR_00(valParSIM,SAUVER,NULL,NULL,NULL);
    return vecNomFichRes;
}

/******************************************************************************************************/
// La but de cette fonction est de faire la synchronie entre des populations locales
// avec les valeurs initiales des variables S0, E0, I0, R0 selon I0
vector<string> faireSYNCH_synchronieI0(int nbVille,vector<double> valParSIM, char SAUVER[5]){
    //villes de synchronie selon I0 -> S0, E0, R0, N0
    //faire une seule population avec tmax = 100 ans = 100*365 = 36500(jours)
    valParSIM[inbVille] = 1;
    valParSIM[itmax] = 36500;
   // valSEIR0.clear();
    cout<<"Fonction 1 : fonctionner une seule population avec tmax = 100ans = 36500 jours"<<endl;
    vector<string> nomFichRes = simulerSEIR_00(valParSIM,SAUVER,NULL,NULL,NULL);

    int sznomFichRes = nomFichRes.size();
    for(int i = 0; i <sznomFichRes; i++ ) cout<<nomFichRes[i]<<endl;
    if(sznomFichRes > 0){
         vector<nodeSEIR> dataSEIR = readTable(nomFichRes[0]);
         double x = 99*365;
         double T = 365;
         cout<<"Fonction 2 : extraire les series SEIR de l'annee 99 à l'annee 100, alors periode = 1ans = 365 jours"<<endl;
         vector<nodeSEIR> serisSEIR = extraireSEIR(x, T, dataSEIR);
         cout<<"Fonction 3 : avec chaque valeur de synchronie, faire la synchronie"<<endl;
         cout<<"Donner la valeur de synchronie dans l'interval [0,1], ySYNCH = ";
         double ySYNCH = donnerChoix();
         cout<<"Donner la valeur de tstart pour connencer à extraire les valeurs SEIR0 dans l'interval [0,365], tstartSYNCH = ";
         double tstartSYNCH = donnerChoix();
         //valSEIR0.clear();
         valParSIM[inbVille] = nbVille;
         vector<nodeSEIR> valSEIR0 = extraireSEIR0(ySYNCH,tstartSYNCH,T,nbVille,serisSEIR);
         vector<string> vecNomFichRes =  simulerSEIR_00(valParSIM,SAUVER,&valSEIR0,NULL,NULL);
         return vecNomFichRes;
    }
    else
    {
        cout<<"Il y a un probleme dans la fonction faireSYNCH_synchronieI0!"<<endl;
        //return vecNomFichRes;
    }
}

/******************************************************************************************************/
// La but de cette fonction est de faire la synchronie entre des populations locales
// avec les valeurs initiales des variables S0, E0, I0, R0 qui sont differentes
vector<string> faireSYNCH_quelconques(int nbVille,vector<double> valParSIM, char SAUVER[5]){
    //Villes quelconque
     vector<nodeSEIR> valSEIR0;
     valParSIM[inbVille] = nbVille;
     valParSIM[itmax] = 36500;
    for(int i = 0; i < nbVille; i++){
        nodeSEIR SEIRtp;
        int ville = i + 1;
        cout<<"Donner les valeurs initiales de SEIR pour ville "<<ville<<endl;
        SEIRtp.t = 0;
        cout<<"S0"<<ville<<" = "; double S0 = donnerChoix(); SEIRtp.S = S0;
        cout<<"E0"<<ville<<" = "; double E0 = donnerChoix(); SEIRtp.E = E0;
        cout<<"I0"<<ville<<" = "; double I0 = donnerChoix(); SEIRtp.I = I0;
        cout<<"R0"<<ville<<" = "; double R0 = donnerChoix(); SEIRtp.R = R0;
        double N0 = S0 + E0 + I0 + R0;
        cout<<"N0"<<ville<<" = S0 + E0 + I0 + R0 = "<<N0<<endl;
        SEIRtp.N = N0;
        SEIRtp.event = 0;
        valSEIR0.push_back(SEIRtp);
    }
     vector<string> vecNomFichRes = simulerSEIR_00(valParSIM,SAUVER,&valSEIR0,NULL,NULL);
     return vecNomFichRes;
}

/******************************************************************/
// Verifier la synchronie avec :
// ySYNCH est dans l'interval[0,1], on va donner une valeur ySYNCHstep, ySYNCH = ySYNCH0 + ySYNCHstep
// Donner un chiffre qui est le nombre de fois le programme refait la synchronie
// Apres avoir fonctionne une simulation, la valeur d'extinction globale est 0 ou 1
// Resutat est un vecteur des valeurs moyennes de nombre d'extinctions globales de chaque ySYNCH
vector<double> verifierSYNCH(vector<double> valParSIM,
                             int nbFoisRESYNCH0 = 100, double ySYNCHstep0 = 0.1){

    int nbVille = valParSIM[inbVille];

    //cout<<"Donner le nombre de fois à refaire la synchronie, nbFoisRESYNCH = ";
    //int nbFoisRESYNCH = donnerChoix();
    int nbFoisRESYNCH = nbFoisRESYNCH0;
    //cout<<"Donner la valeur de la pas [0-1], ySYNCHstep = ";
    //double ySYNCHstep = donnerChoix();
    double ySYNCHstep = ySYNCHstep0;
    double ySYNCH0 = 0.0, ySYNCH = 0.0;
    double extinGlobal, extinTP = 0;
    vector<double> vecExtinGloMoyenne;
    double extinMoyenne = 0;
    vector<string> vecNomFichRes;
    //cout << "En creant un fichier pour sauvegarder le nombre A d'extinction a fonction de chaque valeur de y, NbEXTINCTION...csv"<<endl;
    FILE * fNbEXTINCTION;
    char nomfNbEXTINCTION[255];
    sprintf(nomfNbEXTINCTION,"Output/NbEXTINystep%.1fnbFois%dNbVil%dEps%.4fTop%.1f_SYNCH_ver01_1.csv",ySYNCHstep, nbFoisRESYNCH, nbVille,valParSIM[irho],valParSIM[itopology]);
    cout<<"nom Extin = "<<nomfNbEXTINCTION<<endl;
    fNbEXTINCTION = fopen (nomfNbEXTINCTION,"a+");
    char lEXTINCTION[255];
    sprintf(lEXTINCTION, "y \t\t\t NbExtincMoyenne  \n");
    fputs (lEXTINCTION,fNbEXTINCTION);

    //Mettre les valeurs SEIR0
    //villes de synchronie selon I0 -> S0, E0, R0, N0
    //faire une seule population avec tmax = 100 ans = 100*365 = 36500(jours)
    valParSIM[inbVille] = 1;
    valParSIM[itmax] = 36500;
    vector<nodeSEIR> serisSEIR;
    double tstartSYNCH = 0.0;
    double x = 99*365;
    double T = 365;
    char SAUVER[5] = "Y";
   // valSEIR0.clear();
    //cout<<"Fonction 1 : fonctionner une seule population avec tmax = 100ans = 36500 jours"<<endl;
    vector<string> nomFichRes = simulerSEIR_00(valParSIM,SAUVER,NULL,NULL,NULL);
    int sznomFichRes = nomFichRes.size();

    //cout<<"Fonction 2 : extraire les series SEIR de l'annee 99 à l'annee 100, alors periode = 1ans = 365 jours"<<endl;
    if(sznomFichRes > 0){
         vector<nodeSEIR> dataSEIR = readTable(nomFichRes[0]);
         serisSEIR = extraireSEIR(x, T, dataSEIR);
    }
    else
    {
        cout<<"Il y a un probleme dans la fonction faireSYNCH_synchronieI0!"<<endl;
    }

    //Fonction 3
    valParSIM[inbVille] = nbVille;
    SAUVER[0] = 'N';


    while(ySYNCH <= 1){
        extinGlobal = 0.0;
        //avec chaque valeur de y, on calcule les series SEIR0
        vector<nodeSEIR> valSEIR0 = extraireSEIR0(ySYNCH,tstartSYNCH,T,nbVille,serisSEIR);

        //avec chaque series SEIR0, on execute le programme avec nombre de fois = nbFoisRESYNCH
        for(int i = 0; i < nbFoisRESYNCH; i++){
            vecNomFichRes = simulerSEIR_00(valParSIM,SAUVER,&valSEIR0,NULL,NULL);
            extinTP = 0.0;
            int szVecNomFichRes = vecNomFichRes.size();
            int indexnomfTotal = szVecNomFichRes - 1;
           // cout<<"nom = "<<vecNomFichRes[indexnomfTotal]<<endl;
            vector<nodeSEIR> data = readTable(vecNomFichRes[indexnomfTotal]);
            int szData = data.size();
           // if(data[szData-1].I == 0) extinTP = 1;
           // else extinTP = 0;


            for(int j = 1; j< szData; j++){
                //cout<<"j = "<< j<<"  , I = "<<data[j].I<<endl;
                if(data[j].I == 0) extinTP = extinTP + 1;
            }


            extinGlobal = extinGlobal + extinTP;
           // cout<<"fois = "<<i<<", extinTP = "<< extinTP <<", extinGlobal = "<<extinGlobal <<endl;
        }

        extinMoyenne = (double)extinGlobal/nbFoisRESYNCH;
        vecExtinGloMoyenne.push_back(extinMoyenne);
        sprintf(lEXTINCTION, "%.3f\t\t\t %.5f\n",ySYNCH, extinMoyenne);
        cout<< "ligne = "<<lEXTINCTION<<endl;
        ySYNCH += ySYNCH0 + ySYNCHstep;
        fputs (lEXTINCTION,fNbEXTINCTION);

    }
    fclose(fNbEXTINCTION);
    return vecExtinGloMoyenne;
}


/******************************************************************************************************/
vector<double> verifierSYNCH_ver02(vector<double> valParSIM,
                             int nbFoisRESYNCH0 = 100, double ySYNCHstep0 = 0.1){

    int nbVille = valParSIM[inbVille];
    int nbFoisRESYNCH = nbFoisRESYNCH0;
    double ySYNCHstep = ySYNCHstep0;
    double ySYNCH0 = 0.0, ySYNCH = 0.0;
    double extinGlobal, extinTP = 0;
    vector<double> vecExtinGloMoyenne;
    double extinMoyenne = 0;
    vector<string> vecNomFichRes;

    //cout << "En creant un fichier pour sauvegarder le nombre A d'extinction a fonction de chaque valeur de y, NbEXTINCTION...csv"<<endl;
    FILE * fNbEXTINCTION;
    char nomfNbEXTINCTION[255];
    sprintf(nomfNbEXTINCTION,"Output/NbEXTINystep%.1fnbFois%dNbVil%dEps%.4fTop%.1f_SYNCH_ver02.csv",ySYNCHstep, nbFoisRESYNCH, nbVille,valParSIM[irho],valParSIM[itopology]);
   //cout<<"nom Extin = "<<nomfNbEXTINCTION<<endl;
    fNbEXTINCTION = fopen (nomfNbEXTINCTION,"w+");
    char lEXTINCTION[255];
    sprintf(lEXTINCTION, "y \t\t\t NbExtincMoyenne  \n");
    fputs (lEXTINCTION,fNbEXTINCTION);

    //Mettre les valeurs SEIR0
    vector<nodeSEIR> serisSEIR = readTable("seriesSEIR0.csv");
    double tstartSYNCH = 0.0;
    double T = 0.0;
    char SAUVER[5] = "N";

    int szserisSEIR = serisSEIR.size();
    T = szserisSEIR - 1;

    while(ySYNCH <= 1){
        extinGlobal = 0.0;
        //avec chaque valeur de y, on calcule les series SEIR0
        vector<nodeSEIR> valSEIR0 = extraireSEIR0(ySYNCH,tstartSYNCH,T,nbVille,serisSEIR);

        //avec chaque series SEIR0, on execute le programme avec nombre de fois = nbFoisRESYNCH
        for(int i = 0; i < nbFoisRESYNCH; i++){
            vecNomFichRes = simulerSEIR_00(valParSIM,SAUVER,&valSEIR0,NULL,NULL);
            extinTP = 0.0;
            int szVecNomFichRes = vecNomFichRes.size();
            int indexnomfTotal = szVecNomFichRes - 1;
           // cout<<"nom = "<<vecNomFichRes[indexnomfTotal]<<endl;
            vector<nodeSEIR> data = readTable(vecNomFichRes[indexnomfTotal]);
            int szData = data.size();
            if(data[szData-1].I == 0) extinTP = 1;

            /*
            for(int j = 1; j< szData; j++){
                //cout<<"j = "<< j<<"  , I = "<<data[j].I<<endl;
                if(data[j].I == 0) extinTP = extinTP + 1;
            }
            */

            extinGlobal = extinGlobal + extinTP;
           // cout<<"fois = "<<i<<", extinTP = "<< extinTP <<", extinGlobal = "<<extinGlobal <<endl;
        }

        extinMoyenne = (double)extinGlobal/nbFoisRESYNCH;
        vecExtinGloMoyenne.push_back(extinMoyenne);
        sprintf(lEXTINCTION, "%.3f\t\t\t %.5f\n",ySYNCH, extinMoyenne);
        cout<< "ligne = "<<lEXTINCTION<<endl;
        ySYNCH += ySYNCH0 + ySYNCHstep;
        fputs (lEXTINCTION,fNbEXTINCTION);

    }
    fclose(fNbEXTINCTION);
    return vecExtinGloMoyenne;
}

vector<double> verifierSYNCH_ver03(vector<double> valParSIM,
                             int nbFoisRESYNCH0 = 100, double ySYNCHstep0 = 0.1){

    int nbVille = valParSIM[inbVille];
    int nbFoisRESYNCH = nbFoisRESYNCH0;
    double ySYNCHstep = ySYNCHstep0;
    double ySYNCH0 = 0.0, ySYNCH = 0.0;
    double extinGlobal, extinTP = 0;
    vector<double> vecExtinGloMoyenne;
    double extinMoyenne = 0;
    vector<string> vecNomFichRes;

    //cout << "En creant un fichier pour sauvegarder le nombre A d'extinction a fonction de chaque valeur de y, NbEXTINCTION...csv"<<endl;
    FILE * fNbEXTINCTION;
    char nomfNbEXTINCTION[255];
    sprintf(nomfNbEXTINCTION,"Output/NbEXTINystep%.1fnbFois%dNbVil%dEps%.4fTop%.1f_SYNCH_ver03.csv",ySYNCHstep, nbFoisRESYNCH, nbVille,valParSIM[irho],valParSIM[itopology]);
   //cout<<"nom Extin = "<<nomfNbEXTINCTION<<endl;
    fNbEXTINCTION = fopen (nomfNbEXTINCTION,"w+");
    char lEXTINCTION[255];
    sprintf(lEXTINCTION, "y \t\t\t NbExtincMoyenne  \n");
    fputs (lEXTINCTION,fNbEXTINCTION);

    //Mettre les valeurs SEIR0
    vector<nodeSEIR> serisSEIR = readTable("seriesSEIR0.csv");
    double tstartSYNCH = 0.0;
    double T = 0.0;
    char SAUVER[5] = "N";

    int szserisSEIR = serisSEIR.size();
    T = szserisSEIR - 1;

    while(ySYNCH <= 1){
        extinGlobal = 0.0;
        //avec chaque valeur de y, on calcule les series SEIR0
        vector<nodeSEIR> valSEIR0 = extraireSEIR0(ySYNCH,tstartSYNCH,T,nbVille,serisSEIR);

        //avec chaque series SEIR0, on execute le programme avec nombre de fois = nbFoisRESYNCH
        for(int i = 0; i < nbFoisRESYNCH; i++){
            vecNomFichRes = simulerSEIR_00(valParSIM,SAUVER,&valSEIR0,NULL,NULL);
            extinTP = 0.0;
            int szVecNomFichRes = vecNomFichRes.size();
            int indexnomfTotal = szVecNomFichRes - 1;
           // cout<<"nom = "<<vecNomFichRes[indexnomfTotal]<<endl;
            vector<nodeSEIR> data = readTable(vecNomFichRes[indexnomfTotal]);
            int szData = data.size();

            for(int j = 1; j< szData; j++){
                //cout<<"j = "<< j<<"  , I = "<<data[j].I<<endl;
                if(data[j].I == 0) extinTP = extinTP + 1;
            }

            extinGlobal = extinGlobal + extinTP;
           // cout<<"fois = "<<i<<", extinTP = "<< extinTP <<", extinGlobal = "<<extinGlobal <<endl;
        }

        extinMoyenne = (double)extinGlobal/nbFoisRESYNCH;
        vecExtinGloMoyenne.push_back(extinMoyenne);
        sprintf(lEXTINCTION, "%.3f\t\t\t %.5f\n",ySYNCH, extinMoyenne);
        cout<< "ligne = "<<lEXTINCTION<<endl;
        ySYNCH += ySYNCH0 + ySYNCHstep;
        fputs (lEXTINCTION,fNbEXTINCTION);

    }
    fclose(fNbEXTINCTION);
    return vecExtinGloMoyenne;
}


/******************************************************************************************************/


//
//Verifier la Synchronie simulerSEIR_01, beta est une fonction cos et il y a des phases
vector<nodeSEIR> verifierSYNCH_01_00(vector<double> valParSIM, int nbFoisRESYNCH){
    int nbVill = valParSIM[inbVille];
    double phiMAX = valParSIM[iphiMAX];
    double phiMIN = valParSIM[iphiMIN];
    double *arr_phi = calculerPhases_01(nbVill,phiMAX,phiMIN);

    double rho0 = valParSIM[irho];
    double **arr_rho = calculerTauxCouplage_01(nbVill,rho0);

    vector<string> vecNomFichRes;
    vector<nodeSEIR> vec_PersiGlobale;

    int szVec_PersiGlobale = 0.0;

    double graine = valParSIM[igraine];
    srand(graine);

    //acceuillir les fichiers de resultats (n fichiers pour n villes et encore un autre est le fichier total
    // realiser m=100 simulation independante
    for(int i=0; i<nbFoisRESYNCH; i++){
        vecNomFichRes = simulerSEIR_01(valParSIM,"Y",NULL,arr_phi,arr_rho);

        //voir le fichier global pour la metapopulation
        int szVecNomFichRes = vecNomFichRes.size();
        int indexnomfTotal = szVecNomFichRes - 1;
        //cout<<"nomTOTAL = "<<vecNomFichRes[indexnomfTotal]<<endl;
        vector<nodeSEIR> data = readTable(vecNomFichRes[indexnomfTotal]);
        int szData = data.size();

        for(int j = 0; j< szData; j++){
            if(data[j].I == 0){
               //  cout<<"t = "<< data[j].t<<"  , I = "<<data[j].I<<endl;
                //chen vao vector globale dua theo thu tu thoi gian
                if(i==0) vec_PersiGlobale.push_back(data[j]);
                else{
                szVec_PersiGlobale = vec_PersiGlobale.size();
                for(int k=0; k<szVec_PersiGlobale; k++){
                    if(vec_PersiGlobale[k].t >= data[j].t)
                    {
                        vec_PersiGlobale.insert(vec_PersiGlobale.begin()+k,data[j]);
                        break;
                    }
                    }
                }

            }

        }

    }


    szVec_PersiGlobale = vec_PersiGlobale.size();
    int ff = vec_PersiGlobale.size();
    for(int l=0; l<ff; l++){
        cout<<" t = "<<vec_PersiGlobale[l].t<<" I = "<<vec_PersiGlobale[l].I<<endl;

    }

    return vec_PersiGlobale;
}
/******************************************************************************************************/
//Diviser le temps de simulation selon la chronologie
vector<double> diviserChronologie(double tstart, double tfinal, double unitTemps){
    vector<double> res;
    int nbChronologie = (int)(ceil)(tfinal - tstart)/(unitTemps);
    //cout<<"nbNien dai = "<<nbChronologie<<endl;
    double temps = tstart;
    for(int i = 0; i<nbChronologie; i++){
        res.push_back(temps);
        temps = temps + unitTemps;
        if(i==nbChronologie-1) res.push_back(tfinal);      
    }
    //for(int i=0; i<res.size();i++) cout<<"  "<<res[i]<<endl;
    return res;
}

/******************************************************************************************************/
vector< vector<double > > voirPersiGlobale(vector<double> valParSIM, int nbFoisRESYNCH){
    double tmax = valParSIM[itmax];
    double unitTemps = 365;// valParSIM[iunitTemps];
    vector<double> temps_chrono = diviserChronologie(0.0, tmax, unitTemps);
    vector<vector<double> > vec_M_t;

    vector<nodeSEIR> vec_PersiGlobale = verifierSYNCH_01_00(valParSIM,nbFoisRESYNCH);
    int szVec_PersiGlobale = vec_PersiGlobale.size();

    int szTemps_Chrono =  temps_chrono.size()-1;
    //cout << "En creant un fichier pour sauvegarder le nombre A d'extinction a fonction de chaque valeur de y, NbEXTINCTION...csv"<<endl;
    FILE * fPres_01;
    char nomfPre_01[255];
    sprintf(nomfPre_01,"Output/resPres_01.csv");
    fPres_01 = fopen (nomfPre_01,"w+");
    char lPres_01[255];
    sprintf(lPres_01, "t \t\t\t M  \n");
    fputs (lPres_01,fPres_01);

    double M = 0.0;
    for(int i = 0; i<szTemps_Chrono; i++){
        vector<double> node_M_t;
        M = nbFoisRESYNCH;

        for(int j=0; j<szVec_PersiGlobale; j++){
            if(( temps_chrono[i]<= vec_PersiGlobale[j].t)&&(vec_PersiGlobale[j].t < temps_chrono[i+1]))
                M = M - 1.0;
        }

        node_M_t.push_back(temps_chrono[i]);
        node_M_t.push_back(M);
        vec_M_t.push_back(node_M_t);
    }

    int sz = vec_M_t.size();
    for(int i=0; i<sz; i++){
        sprintf(lPres_01, "%.1f\t\t\t %.1f\n",vec_M_t[i][0], vec_M_t[i][1]);
        fputs (lPres_01,fPres_01);

    }
    return vec_M_t;

}
/******************************************************************************************************/
